package com.uinnova.product.eam.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.binary.core.exception.MessageException;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.comm.exception.BusinessException;
import com.uinnova.product.eam.comm.model.CVcBaseConfig;
import com.uinnova.product.eam.comm.model.VcBaseConfig;
import com.uinnova.product.eam.comm.model.es.EamArtifactElement;
import com.uinnova.product.eam.model.EamArtifactVo;
import com.uinnova.product.eam.model.constants.DmvConstants;
import com.uinnova.product.eam.model.diagram.DiagramNodeLinkInfo;
import com.uinnova.product.eam.model.dto.CiCodeDto;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.es.IamsESCICommSvc;
import com.uinnova.product.eam.service.es.IamsEamESCIClassSvc;
import com.uinnova.product.eam.service.utils.VisualModelUtils;
import com.uinnova.product.vmdb.comm.model.ci.CCcCiClass;
import com.uinnova.product.vmdb.comm.model.ci.CcCiAttrDef;
import com.uinnova.product.vmdb.comm.util.PropertyType;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uino.bean.cmdb.base.*;
import com.uino.bean.cmdb.enums.AttrNameKeyEnum;
import com.uino.bean.cmdb.query.ESCISearchBean;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.sys.base.ESDictionaryAttrDef;
import com.uino.bean.sys.base.ESDictionaryClassInfo;
import com.uino.bean.sys.query.ESDictionaryItemSearchBean;
import com.uino.dao.BaseConst;
import com.uino.dao.cmdb.*;
import com.uino.dao.util.ESUtil;
import com.uino.service.cmdb.microservice.ICIClassEncodeSvc;
import com.uino.service.sys.microservice.IDictionarySvc;
import com.uino.util.sys.CheckAttrUtil;
import com.uino.util.sys.SysUtil;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * @author zoumengjie
 *
 */
@Service
public class EamCIClassSvc implements IEamCIClassApiSvc {

    @Autowired
    private IamsEamESCIClassSvc esciClassSvc;

    @Autowired
    private ICIClassEncodeSvc encodeSvc;

    @Autowired
    private IamsESCICommSvc esCiSvc;

    @Autowired
    private ESDirSvc esDirSvc;

    @Autowired
    private ICISwitchSvc ciSwitchSvc;

    @Autowired
    private ESCIAttrTransConfigSvc attrTransConfigSvc;

    @Resource
    private ESVisualModelSvc esVisualModelSvc;
    @Resource
    private IEamArtifactSvc artifactSvc;
    @Resource
    private IEamArtifactColumnSvc artifactColumnSvc;
    @Autowired
    @Lazy
    private ESCmdbCommSvc commSvc;

    @Autowired
    private IDictionarySvc dictSvc;

    @Resource
    private BaseConfigService baseConfigService;

    @Value("${http.resource.space}")
    private String rsmSlaveRoot;

    @Value("${uino.base.ci.primarykey.maxcount:5}")
    private Integer primaryKeyCount;
    @Override
    public Long saveOrUpdateESCIClass(ESCIClassInfo esClsInfo) {
        if (esClsInfo.getDomainId() == null) {
            esClsInfo.setDomainId(BaseConst.DEFAULT_DOMAIN_ID);
        }
        boolean isAdd = esClsInfo.getId() == null;
        validAndBuild(esClsInfo);
        String imgNameRegex = ".*[.](jpg|png|gif|jpeg|bmp|tiff|pcx|tga|exif|fpx|svg|psd|cdr|pcd|dxf|ufo|eps|ai|raw|WMF)";
        Assert.isTrue(esClsInfo.getIcon().matches(imgNameRegex), "不支持的图标类型");
        SysUser loginUser = null;
        try {
            loginUser = SysUtil.getCurrentUserInfo();
        } catch (Exception e) {
        }
        String classStdName = esClsInfo.getClassStdName();
        Assert.isTrue(!BinaryUtils.isEmpty(esDirSvc.getById(esClsInfo.getDirId())), "所属领域不存在！");

        List<ESCIClassInfo> allClassList = esciClassSvc.selectListByQuery(1, 3000, QueryBuilders.termQuery("domainId", esClsInfo.getDomainId()));
        Map<String, Long> clsIdMap = allClassList.stream().filter(Objects::nonNull).collect(Collectors.toMap(each -> each.getClassName().toUpperCase(), each -> each.getId(), (k1, k2) -> k1));
        boolean exist = clsIdMap.containsKey(classStdName);
        if (!isAdd && exist) {
            Long dbClassId = clsIdMap.get(classStdName);
            exist = dbClassId.longValue() != esClsInfo.getId().longValue();
        }
        if(exist){
            throw new BinaryException("分类名称已存在");
        }
        //Assert.isTrue(BinaryUtils.isEmpty(esciClassSvc.getListByQuery(clsNameQuery)), "分类名称已存在");
        // 校验分类标识重复
        String classStdCode = esClsInfo.getClassStdCode();
        BoolQueryBuilder clsCodeQuery = QueryBuilders.boolQuery();
        clsCodeQuery.must(QueryBuilders.termQuery("domainId", esClsInfo.getDomainId()));
        clsCodeQuery.must(QueryBuilders.termQuery("classStdCode.keyword", classStdCode));
        if (!isAdd) {
            clsCodeQuery.mustNot(QueryBuilders.termQuery("id", esClsInfo.getId()));
        }
        Assert.isTrue(BinaryUtils.isEmpty(esciClassSvc.getListByQuery(clsCodeQuery)), "分类标识已存在");
        if(!isAdd){
            List<ESCIClassInfo> esciClassInfos = selectCiClassByIds(Collections.singletonList(esClsInfo.getId()));
            if(!esClsInfo.getClassStdCode().equals(esciClassInfos.get(0).getClassStdCode())){
                for (LibType libType : LibType.values()) {
                    ESCISearchBean bean = new ESCISearchBean();
                    bean.setPageNum(1);
                    bean.setPageSize(1);
                    bean.setClassIds(Collections.singletonList(esClsInfo.getId()));
                    bean.setDomainId(esClsInfo.getDomainId());
                    Page<ESCIInfo> ciPage = ciSwitchSvc.searchESCIByBean(bean, libType);
                    if(!BinaryUtils.isEmpty(ciPage.getData())){
                        throw new BinaryException("该分类下存在数据,不支持修改分类标识");
                    }
                }
            }
        }
        // 校验属性重复
        List<String> proNames = new ArrayList<>();
        if (esClsInfo.getParentId() != null && esClsInfo.getParentId().longValue() != 0) {
            ESCIClassInfo parClass = esciClassSvc.getById(esClsInfo.getParentId());
            Assert.isTrue(!BinaryUtils.isEmpty(parClass), "BS_PARNET_CLASS_NOT_EXIST");
            Assert.isTrue(parClass.getParentId() == 0, "至多可创建一级子类");
            List<String> parDefs = parClass.getCcAttrDefs().stream().map(CcCiAttrDef::getProStdName).collect(Collectors.toList());
            proNames.addAll(parDefs);
        } else if (!isAdd) {
            List<ESCIClassInfo> list = esciClassSvc.getListByQuery(QueryBuilders.termQuery("parentId", esClsInfo.getId()));
            list.forEach(cls -> proNames.addAll(cls.getCcAttrDefs().stream().map(CcCiAttrDef::getProStdName).collect(Collectors.toList())));
        }
        List<CcCiAttrDef> attrDefs = esClsInfo.getCcAttrDefs();
        for (CcCiAttrDef attrDef : attrDefs) {
            String proStdName = attrDef.getProStdName();
            Assert.isTrue(!proNames.contains(proStdName), "BS_CC_CLASS_DEF_EXIST${proName:" + proStdName + "}");
            proNames.add(proStdName);
            // attrDef.setId(attrDef.getId() == null ? ESUtil.getUUID() :
            // attrDef.getId());
        }
              if (isAdd) {
            esClsInfo.setCreator(loginUser == null ? "system" : loginUser.getLoginCode());
        } else {
            // 保持子分类与父分类所属同领域
            esciClassSvc.updateByQuery(QueryBuilders.termQuery("parentId", esClsInfo.getId()), "ctx._source.dirId=" + esClsInfo.getDirId() + "L", true);
            esClsInfo.setModifier(loginUser == null ? "system" : loginUser.getLoginCode());
        }
        return esciClassSvc.saveOrUpdate(esClsInfo);
    }

    @Override
    public Integer removeCIClassById(Long id) {
        CVcBaseConfig wallCdt = new CVcBaseConfig();
        //wallCdt.setCfgCode(DmvConstants.APP_WALL_CONFIG);
        wallCdt.setCfgCodes(new String[]{DmvConstants.APP_WALL_CONFIG,DmvConstants.DOMAIN_CONFIG});
        List<VcBaseConfig> vcBaseConfigs = baseConfigService.queryBaseConfigList(wallCdt);
        if (!CollectionUtils.isEmpty(vcBaseConfigs)) {
            for (VcBaseConfig vcBaseConfig : vcBaseConfigs) {
                //VcBaseConfig vcBaseConfig = vcBaseConfigs.get(0);
                String cfgContent = vcBaseConfig.getCfgContent();
                if (!StringUtils.isEmpty(cfgContent)) {
                    JSONObject appWallJson = JSONObject.parseObject(cfgContent);
                    Long classId = appWallJson.getLong("appClass");
                    if (classId != null && Objects.equals(id, classId)) {
                        throw new BusinessException("删除失败，分类已被应用全景配置引用!");
                    }
                }
            }
        }
        List<ESCIClassInfo> childs = esciClassSvc.getListByQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("parentId", id)));
        List<String> childNames = childs.stream().map(ESCIClassInfo::getClassName).collect(Collectors.toList());
        if (!BinaryUtils.isEmpty(childs)) {
            throw MessageException.i18n("BS_CLASS_DELETE_EXIST_SUB_CLASS", "{\"field\":\"" + StringUtils.join(childNames, ",") + "\"}");
        }
        esCiSvc.getLibTypes().forEach(libType -> {
            Map<Object, Long> countMap = esCiSvc.countCIByQuery(QueryBuilders.termQuery("classId", id), libType);
            Long count = countMap.get(id);
            if (count != null && count > 0) {
                throw MessageException.i18n("BS_CC_CLASS_HAS_DATA");
            }
        });
        attrTransConfigSvc.deleteByQuery(QueryBuilders.termQuery("classId", id), false);
        esCiSvc.getLibTypes().forEach(libType -> esCiSvc.deleteHistoryByQuery(QueryBuilders.termQuery("classId", id), false, libType));
        // ciHistorySvc.deleteByQuery(QueryBuilders.termQuery("classId", id), false);
        return esciClassSvc.deleteById(id);
    }

    @Override
    public List<ESCIClassInfo> selectCiClassByIds(List<Long> classIds){
        CCcCiClass cdt = new CCcCiClass();
        cdt.setIds(classIds.toArray(new Long[classIds.size()]));
        List<SortBuilder<?>> sorts = new ArrayList<>();
        SortBuilder<?> classNameSort = SortBuilders.fieldSort("className.keyword").order(SortOrder.ASC);
        SortBuilder<?> timeSort = SortBuilders.fieldSort("createTime").order(SortOrder.DESC);
        sorts.add(classNameSort);
        sorts.add(timeSort);
        List<ESCIClassInfo> classInfos = esciClassSvc.getSortListByCdt(cdt, sorts);
        esciClassSvc.transAttrDefsToShowName(classInfos);
        for (ESCIClassInfo classInfo : classInfos) {
            classInfo.setIcon(rsmSlaveRoot + classInfo.getIcon());
        }
        return classInfos;
    }

    @Override
    public String getEnCodeNum(CiCodeDto dto) {
        Long maxNum = encodeSvc.getMaxNum(dto.getClassCode(), dto.getProName(), 1L, LibType.DESIGN);
        return dto.getDefVal() + "[" + maxNum + "]";
    }

    @Override
    public void clearCacheEncode(List<Long> classIds) {
        encodeSvc.clearCacheEncode(classIds);
    }

    @Override
    public Map<Long, ESCIClassInfo> copyCIClassByIds(List<Long> ids) {
        // 根据ids校验分类信息是否存在
        List<ESCIClassInfo> esciClassInfos = esciClassSvc.getListByQuery(QueryBuilders.termsQuery("id", ids));
        if (CollectionUtils.isEmpty(esciClassInfos) || esciClassInfos.size() < ids.size()) {
            throw new BinaryException("分类信息不存在");
        }
        Map<Long, ESCIClassInfo> oldAndNewIds = new HashMap<>();
        // 封装保存对象
        for (ESCIClassInfo esciClassInfo : esciClassInfos) {
            // 处理 className 字段
            String newCIClassName = this.checkName(esciClassInfo.getClassName());
            ESCIClassInfo newESciClassInfo = new ESCIClassInfo();
            List<ESCIAttrDefInfo> attrDefs = esciClassInfo.getAttrDefs();
            attrDefs.forEach(e -> {
                e.setId(null);
                e.setClassId(null);
            });
            newESciClassInfo.setAttrDefs(attrDefs);
            newESciClassInfo.setClassName(newCIClassName);
            newESciClassInfo.setDirId(esciClassInfo.getDirId());
            newESciClassInfo.setParentId(esciClassInfo.getParentId());
            newESciClassInfo.setCiType(esciClassInfo.getCiType());
            newESciClassInfo.setIcon(esciClassInfo.getIcon());
            Long newId = this.saveOrUpdateESCIClass(newESciClassInfo);
            ESCIClassInfo reData = new ESCIClassInfo();
            reData.setId(newId);
            reData.setClassName(newCIClassName);
            reData.setClassCode(newESciClassInfo.getClassCode());
            oldAndNewIds.put(esciClassInfo.getId(), reData);
        }
        return oldAndNewIds;
    }

    @Override
    public CcCiClassInfo getCIClassByCodes(String classCodes) {
        Assert.notNull(classCodes, "分类标识");
        CcCiClassInfo data = new CcCiClassInfo();
        SysUser currentUserInfo = SysUtil.getCurrentUserInfo();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("domainId", currentUserInfo.getDomainId()));
        boolQueryBuilder.must(QueryBuilders.termQuery("classCode.keyword", classCodes));
        List<ESCIClassInfo> listByQuery = esciClassSvc.getListByQuery(boolQueryBuilder);
        if (CollectionUtils.isEmpty(listByQuery)) {
            return data;
        }
        return commSvc.tranCcCiClassInfo(listByQuery.get(0));
    }

    @Override
    public ESCIClassInfo getCIClassByCode(String classCodes) {
        Assert.notNull(classCodes, "分类标识");
        ESCIClassInfo data = new ESCIClassInfo();
        SysUser currentUserInfo = SysUtil.getCurrentUserInfo();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("domainId", currentUserInfo.getDomainId()));
        boolQueryBuilder.must(QueryBuilders.termQuery("classCode.keyword", classCodes));
        List<ESCIClassInfo> list = esciClassSvc.getListByQuery(boolQueryBuilder);
        if (CollectionUtils.isEmpty(list)) {
            return data;
        }
        esciClassSvc.transAttrDefsToShowName(list);
        return list.get(0);
    }

    @Override
    public List<CcCiClassInfo> getByClassCodes(Collection<String> classCodes, Long domainId) {
        if(domainId == null){
            domainId = BaseConst.DEFAULT_DOMAIN_ID;
        }
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("domainId", domainId));
        boolQueryBuilder.must(QueryBuilders.termsQuery("classCode.keyword", classCodes));
        List<ESCIClassInfo> listByQuery = esciClassSvc.getListByQuery(boolQueryBuilder);
        if (CollectionUtils.isEmpty(listByQuery)) {
            return Collections.emptyList();
        }
        return listByQuery.stream().map(each -> commSvc.tranCcCiClassInfo(each)).collect(Collectors.toList());
    }

    @Override
    public ESCIClassInfo queryClassById(Long id) {
        return esciClassSvc.getById(id);
    }

    public String checkName(String name) {
        name = name + "_副本";
        List<ESCIClassInfo> listByQuery = esciClassSvc.getListByQuery(QueryBuilders.termQuery("className.keyword", name));
        if (CollectionUtils.isEmpty(listByQuery)) {
            return name;
        }
        for (int i = 2; i <= 1000; i ++) {
            List<ESCIClassInfo> listByQueryNum = esciClassSvc.getListByQuery(QueryBuilders.termQuery("className.keyword", name + i));
            if (CollectionUtils.isEmpty(listByQueryNum)) {
                return name + i;
            }
        }
        return name;
    }

    public void validAndBuild(ESCIClassInfo esClsInfo) {
        Assert.isTrue(!BinaryUtils.isEmpty(esClsInfo.getClassName()), "分类名称不能为空");
        Assert.isTrue(!BinaryUtils.isEmpty(esClsInfo.getClassName().trim()), "分类名称不能为空");
        Assert.isTrue(esClsInfo.getClassName().matches("[^\\:\\/\\?\\*\\[\\]\\\\]{1,30}"), "分类名称不可超过30位，且不可包含:/\\?*[]等字符");
        boolean defaultClassCode = BinaryUtils.isEmpty(esClsInfo.getClassCode());
        if(!defaultClassCode){
            Assert.isTrue(esClsInfo.getClassCode().matches("[^\\:\\/\\?\\*\\[\\]\\\\]{1,30}"), "分类标识不可超过30位，且不可包含:/\\?*[]等字符");
        }
        SysUser loginUser = null;
        try {
            loginUser = SysUtil.getCurrentUserInfo();
        } catch (Exception e) {
        }
        Long domainId = loginUser == null ? 1L : loginUser.getDomainId();
        // 丰富分类信息
        if (esClsInfo.getId() == null) {
            esClsInfo.setId(ESUtil.getUUID());
            esClsInfo.setParentId(esClsInfo.getParentId() == null ? 0 : esClsInfo.getParentId());
            esClsInfo.setCiType(1);
            esClsInfo.setDataStatus(1);
            esClsInfo.setIsLeaf(BinaryUtils.isEmpty(esClsInfo.getIsLeaf()) ? 1 : esClsInfo.getIsLeaf());
            esClsInfo.setDomainId(domainId);
            esClsInfo.setClassLvl(BinaryUtils.isEmpty(esClsInfo.getClassLvl()) ? 1 : esClsInfo.getClassLvl());
            esClsInfo.setCreator(loginUser == null ? "system" : loginUser.getLoginCode());
            esClsInfo.setCreateTime(ESUtil.getNumberDateTime());
        }
        esClsInfo.setClassPath("#" + esClsInfo.getId() + "#");
        if (esClsInfo.getParentId() != null && esClsInfo.getParentId().longValue() != 0) {
            esClsInfo.setClassLvl(2);
            esClsInfo.setClassPath("#" + esClsInfo.getParentId() + esClsInfo.getClassPath());
        } else {
            // 非子分类，属性不可为空
            Assert.notEmpty(esClsInfo.getCcAttrDefs(), "属性定义不能为空");
        }
        if(defaultClassCode){
            esClsInfo.setClassCode(esClsInfo.getId().toString());
        }
        esClsInfo.setClassStdCode(esClsInfo.getClassCode().trim().toUpperCase());
        esClsInfo.setClassName(esClsInfo.getClassName().trim());
        esClsInfo.setClassStdName(esClsInfo.getClassName().toUpperCase());
        esClsInfo.setModifier(loginUser == null ? "system" : loginUser.getLoginCode());
        // 丰富icon信息
        String icon = BinaryUtils.isEmpty(esClsInfo.getIcon()) ? esciClassSvc.getDefaultIcon() : esClsInfo.getIcon();
        if (!BinaryUtils.isEmpty(icon) && icon.startsWith(rsmSlaveRoot)) {
            icon = icon.substring(rsmSlaveRoot.length(), icon.length());
        }
        esClsInfo.setIcon(icon);
        List<CcCiAttrDef> attrDefs = esClsInfo.getCcAttrDefs();
        if (!BinaryUtils.isEmpty(attrDefs)) {
            // 校验主键数量
            List<CcCiAttrDef> majorDefs = attrDefs.stream().filter(def -> (def.getIsMajor() != null && def.getIsMajor().longValue() == 1)).collect(Collectors.toList());
            Assert.isTrue(esClsInfo.getParentId().longValue() == 0 || majorDefs.size() <= 0, "子分类不允许设置主键");
            if (esClsInfo.getParentId() == null || esClsInfo.getParentId().longValue() == 0) {
                Assert.isTrue(!BinaryUtils.isEmpty(majorDefs), "缺少业务主键");
            }
            Assert.isTrue(majorDefs.size() <= primaryKeyCount, "主键数量超过最大限制:" + primaryKeyCount);
            majorDefs.forEach(majorDef -> {
                Assert.isTrue(PropertyType.LONG_VARCHAR.getValue() != majorDef.getProType() && PropertyType.CLOB.getValue() != majorDef.getProType(), "文本、文章类型不可作为主键");
            });
            // 丰富属性信息
            for (CcCiAttrDef attrDef : attrDefs) {
                Assert.isTrue(!BinaryUtils.isEmpty(attrDef.getProName().trim()), "属性名称不得为空");
                Assert.isTrue(attrDef.getProName().trim().matches("^[A-Za-z0-9\\u4e00-\\u9fa5 @\\（\\）\\(\\)\\&\\-\\|\\/\\\\'_]+$"), "属性[" + attrDef.getProName() + "]包含非法字符，仅支持 _&()（）|/\\'-@");
                //去除分类属性名称前后空格
                attrDef.setProName(attrDef.getProName().trim());
                // 验证枚举值定义是否符合规范
                if (AttrNameKeyEnum.ENUM.getType() == attrDef.getProType().intValue()) {
                    Assert.isTrue(!BinaryUtils.isEmpty(attrDef.getEnumValues()), "枚举型类型约束不可为空");
                    List<String> enumValues = JSONArray.parseArray(attrDef.getEnumValues(), String.class);
                    for (String enumVal : enumValues) {
                        Integer checkResult = CheckAttrUtil.validateAttrValType(attrDef, enumVal);
                        switch (checkResult) {
                            case CheckAttrUtil.OVER_LENGTH:
                                Assert.isTrue(false, "枚举值[" + enumVal + "]超过类型限定长度");
                                break;
                            case CheckAttrUtil.FORMAT_ERROR:
                                Assert.isTrue(false, "枚举值[" + enumVal + "]格式错误");
                                break;
                            default:
                                break;
                        }
                    }
                } else if (AttrNameKeyEnum.DICT.getType() == attrDef.getProType().intValue()) {
                    Assert.isTrue(!BinaryUtils.isEmpty(attrDef.getProDropSourceDef()), "字典引用类型约束不可为空");
                    try {
                        @SuppressWarnings("unchecked")
                        Long dictClassId = CiClassProDropSourceDefHelper.getCiClassProDropSourceClassId(attrDef.getProDropSourceDef().trim());
                        Long[] dictDefIds = CiClassProDropSourceDefHelper.getCiClassProDropSourceDefIds(attrDef.getProDropSourceDef().trim());
                        ESDictionaryItemSearchBean bean = ESDictionaryItemSearchBean.builder().dictClassId(dictClassId).build();
                        List<ESDictionaryClassInfo> dictClsList = dictSvc.queryDcitClassInfosByBean(bean);
                        Assert.notEmpty(dictClsList, "属性[" + attrDef.getProName().toUpperCase() + "]引用不合法");
                        Map<Long, Integer> dictDefMap = dictClsList.get(0).getDictAttrDefs().stream().collect(Collectors.toMap(ESDictionaryAttrDef::getId, ESDictionaryAttrDef::getProType));
                        for (Long dictDefId : dictDefIds) {
                            Integer dictType = dictDefMap.get(dictDefId);
                            // 引用类型不能是文件或其他字典引用
                            Assert.isTrue(dictType != null && dictType.intValue() != ESDictionaryAttrDef.DictProTypeEnum.EXTERNAL_DICT.getType()
                                    && dictType.intValue() != ESDictionaryAttrDef.DictProTypeEnum.FILE.getType(), "属性[" + attrDef.getProName().toUpperCase() + "]引用不合法");
                        }
                    } catch (Exception e) {
                        Assert.isTrue(false, "属性[" + attrDef.getProName().toUpperCase() + "]引用不合法");
                    }
                }
                Integer checkResult = CheckAttrUtil.validateAttrValType(attrDef, attrDef.getDefVal());
                switch (checkResult) {
                    case CheckAttrUtil.OVER_LENGTH:
                        Assert.isTrue(false, "属性[" + attrDef.getProName() + "]默认值超过类型限定长度");
                        break;
                    case CheckAttrUtil.FORMAT_ERROR:
                        Assert.isTrue(false, "属性[" + attrDef.getProName() + "]默认值格式错误");
                        break;
                    default:
                        break;
                }
                attrDef.setDomainId(1L);
                attrDef.setDataStatus(1);
                attrDef.setCreateTime(ESUtil.getNumberDateTime());
                attrDef.setProStdName(attrDef.getProName().trim().toUpperCase());
                // attrDef.setOrderNo(attrDefs.indexOf(attrDef) + 1);
                attrDef.setIsMajor(attrDef.getIsMajor() == null || attrDef.getIsMajor() != 1 ? 0 : 1);
                Integer isRequired = attrDef.getIsMajor().intValue() == 1 ? 1 : (attrDef.getIsRequired() == null || attrDef.getIsRequired() != 1 ? 0 : 1);
                attrDef.setIsRequired(isRequired);
                attrDef.setIsCiDisp(attrDef.getIsCiDisp() == null || attrDef.getIsCiDisp() != 1 ? 0 : 1);
                attrDef.setProType(attrDef.getProType() == null ? 3 : attrDef.getProType());
            }
        }
    }

    @Override
    public CcCiClassInfo queryClassAndAttrMappingByCode(String classCode) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("domainId", SysUtil.getCurrentUserInfo().getDomainId()));
        boolQueryBuilder.must(QueryBuilders.termQuery("classCode.keyword", classCode));
        List<ESCIClassInfo> listByQuery = esciClassSvc.getListByQuery(boolQueryBuilder);
        if (CollectionUtils.isEmpty(listByQuery)) {

            throw new BinaryException("该分类信息不存在");
        }
        ESCIClassInfo classSvcById = esciClassSvc.getById(listByQuery.get(0).getId());
        CcCiClassInfo classInfo1 = commSvc.tranCcCiClassInfo(classSvcById);
        return classInfo1;
    }

    @Override
    public List<ESCIClassInfo> getCIClassList(String word) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("domainId", SysUtil.getCurrentUserInfo().getDomainId()));
//        if (!BinaryUtils.isEmpty(word)) {
//            boolQueryBuilder.must(QueryBuilders.termQuery("className", word));
//        }
        List<ESCIClassInfo> result = esciClassSvc.selectListByQuery(1, 3000, boolQueryBuilder);
        esciClassSvc.transAttrDefsToShowName(result);
        return result;
    }

    @Override
    public List<ESCIClassInfo> filterByVisualModel(Long id) {
        Long domainId = SysUtil.getCurrentUserInfo().getDomainId();
        //1.获取当前使用的元模型信息
        ESVisualModel esVisualModel = esVisualModelSvc.getEnableModel(domainId);
        if (BinaryUtils.isEmpty(esVisualModel.getJson())) {
            return Collections.emptyList();
        }
        //获取元模型中存在的ClassId
        Set<Long> ciClassIds = new HashSet<>();
        List<DiagramNodeLinkInfo> rltLinkList = VisualModelUtils.getRltClassIds(esVisualModel);
        for (DiagramNodeLinkInfo link : rltLinkList) {
            if(!link.getSourceId().equals(id) && !link.getTargetId().equals(id)){
                continue;
            }
            Long targetClassId = link.getSourceId().equals(id) ? link.getTargetId() : link.getSourceId();
            ciClassIds.add(targetClassId);
        }
        if (BinaryUtils.isEmpty(ciClassIds)) {
            return Collections.emptyList();
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("domainId", domainId));
        queryBuilder.must(QueryBuilders.termsQuery("id", ciClassIds));
        List<ESCIClassInfo> result = esciClassSvc.getListByQuery(queryBuilder);
        return CollectionUtils.isEmpty(result)?Collections.emptyList() : result;
    }

    @Override
    public Boolean checkEdit(Long id) {
        Long domainId = SysUtil.getCurrentUserInfo().getDomainId();
        ESVisualModel esVisualModel = esVisualModelSvc.getEnableModel(domainId);
        if (esVisualModel == null || BinaryUtils.isEmpty(esVisualModel.getJson())) {
            return true;
        }
        //获取元模型中存在的ClassId
        Set<Long> classIds = VisualModelUtils.getCiClassIds(esVisualModel);
        if(classIds.contains(id)){
            return false;
        }
        //校验制品中是否使用
        List<EamArtifactVo> artifactList = artifactSvc.queryByType(null);
        if(CollectionUtils.isEmpty(artifactList)){
            return true;
        }
        List<Long> ids = artifactList.stream().map(EamArtifactVo::getId).collect(Collectors.toList());
        Map<Long, List<EamArtifactElement>> elements = artifactColumnSvc.queryByIdsAndType(ids, Lists.newArrayList(1, 2));
        String checkId = id.toString();
        for (Map.Entry<Long, List<EamArtifactElement>> entry : elements.entrySet()) {
            for (EamArtifactElement element : entry.getValue()) {
                for (String each : element.getElements()) {
                    if(each.contains(checkId)){
                        return false;
                    }
                }
            }
        }
        return true;
    }
}
